package com.rtx.express.handle.impl;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.rtx.api.annotation.DataSourceAnnotation;
import com.rtx.edi.model.api.bo.ApiMappingInfoBo;
import com.rtx.edi.model.express.bo.ExpressBO;
import com.rtx.edi.model.express.po.PlExpressResult;
import com.rtx.express.handle.ConfigExpress;
import com.rtx.express.handle.ExpressCollectHandle;
import com.rtx.express.service.IExpressService;
import com.rtx.wms.std.express.bean.ExpressOrders;
import com.rtx.wms.std.express.bean.PlExpressResultBak;
import com.rtx.wms.std.express.service.ExpressOrdersService;
import com.rtx.wms.std.express.service.ExpressResultService;
import com.rtx.wms.std.express.service.PlExpressResultBakService;

import cn.hutool.core.lang.UUID;

@Service
public class ConfigExpressImpl implements ConfigExpress{

	Logger log = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	ExpressOrdersService expressOrdersService;
	
	@Autowired
	ExpressCollectHandle expressCollectHandle;
	
	@Autowired
	ExpressResultService expressResultService;
	
	@Autowired
	PlExpressResultBakService expressResultBakService;
	
	@Autowired
	ApplicationContext appContext;

	
	@DataSourceAnnotation
	public void handleExpressSchedul(String datasourcekey,ApiMappingInfoBo ediConfig) {

		List<ExpressOrders> list  = expressOrdersService.queryByOrdersByConfig(datasourcekey, ediConfig);
		String status ="";

		for(ExpressOrders order:list) {
			String msg ="ok";
			try {
				String orderkey = order.getOrderkey();
				ExpressBO bo = new ExpressBO();
				bo.setWmwsheid(datasourcekey);
				bo.setZdflag(false);
				bo.setEdiConfig(ediConfig);

				//收集并且校验数据
				bo = expressCollectHandle.collectExpressInfoByOrderkey(datasourcekey,orderkey,bo,ediConfig);

				IExpressService expressService = appContext.getBean(bo.getExpressConfig().getExpressapi(),IExpressService.class);

				Assert.notNull(expressService, "快递接口-"+bo.getExpressConfig().getExpressapi()+"-未实现");

				expressService.callCreaterOrderAPI(bo);

				expressService.handleCreaterOrderAPIResponse(bo);


				if("ok".equals(bo.getCallCreateOrderAPIResult())) {
					bo.getExpressResult().setCarriercode(bo.getExpressConfig().getCarriercode());
					
					String mailNo = Optional.ofNullable(bo.getExpressResult().getWaybillNo()).orElse("");
					String printData = Optional.ofNullable(bo.getExpressResult().getPrintData()).orElse("");
					//当为快递平台调用云打印，打印数据为空认为获取快递单号失败
					if(Arrays.asList("DY,JDWJ,PDD,TM".split(",")).contains(bo.getExpressConfig().getExpressapi()) && !StringUtils.hasLength(printData)) {
						msg =bo.getExpressConfig().getExpressapi()+"平台接口获取打印数据失败";
						status ="F";
					}else {
						//将获取快递单号结果写入中间表
						handelExpressResult(bo,"");
						
						expressOrdersService.updExpressData(datasourcekey,mailNo, printData, orderkey);
					}
				}else {
					msg = bo.getMsg()+bo.getCallCreateOrderAPIData();;
					status ="F";
				}
			} catch (Exception e) {
				log.error("获取快递单号异常-",e);
				msg = e.getMessage();
				status ="F";
			}


			
			String notNullMsg = Optional.ofNullable(msg).orElse("");
			String msgUseable = notNullMsg.length()>499?notNullMsg.substring(0,490):notNullMsg;

			if("ok".equals(msg)) {
				status ="S";
			}else {
				status ="F";
			}

			expressOrdersService.updExpressStatus(datasourcekey,status, msgUseable, order.getOrderkey());
		}



	}
	
	//request:{"orderkey":"","whseid":""}
	//response:{"code":"S或者F","msg":"","mailno":""}
	@DataSourceAnnotation
	public String handleExpress(String datasourcekey,String bodyStr,ApiMappingInfoBo ediConfig) {
		String uuid = UUID.randomUUID().toString();
		
		log.info("uuid-{}-获取新快递单号-{}",uuid,bodyStr);
		JSONObject res = new JSONObject();
		try {
			
			JSONObject wmsRequest = JSON.parseObject(bodyStr);
			String orderkey = wmsRequest.getString("orderkey");
			String zdflag = Optional.ofNullable(wmsRequest.getString("zdflag")).orElse("") ;
			ExpressBO bo = new  ExpressBO();
			bo.setWmwsheid(datasourcekey);
			bo.setEdiConfig(ediConfig);
			
			if("false".equals(zdflag)) {
				bo.setZdflag(false);
			}else {
				bo.setZdflag(true);
			}
			
			//获取快递单号数据
			expressCollectHandle.collectExpressInfoByOrderkey(datasourcekey,orderkey,bo,ediConfig);
			
			IExpressService expressService =  appContext.getBean(bo.getExpressConfig().getExpressapi(),IExpressService.class);
			
			Assert.notNull(expressService, "快递接口-"+bo.getExpressConfig().getExpressapi()+"-未实现");
			
			//调用快递接口
			expressService.callCreaterOrderAPI(bo);
			
			expressService.handleCreaterOrderAPIResponse(bo);

			if("ok".equals(bo.getCallCreateOrderAPIResult())) {
				bo.getExpressResult().setCarriercode(bo.getExpressConfig().getCarriercode());

//				plExpressResultMapper.insert(bo.getExpressResult());
				//处理中间表
				handelExpressResult(bo,bodyStr);
				
				String mailNo = Optional.ofNullable(bo.getExpressResult().getWaybillNo()).orElse("");
				String printData = Optional.ofNullable(bo.getExpressResult().getPrintData()).orElse(" ");
				if(StringUtils.hasLength(mailNo)&&StringUtils.hasLength(printData)) {
					if(!bo.getZdflag()) {
						expressOrdersService.updExpressData(datasourcekey,mailNo, printData, orderkey);
					}
				}
				res.put("code", "S");
				res.put("msg", "success");
				res.put("mailno", bo.getExpressResult().getWaybillNo());
			}else {
				res.put("code", "F");
				res.put("msg", bo.getMsg());
				res.put("mailno", "");
			}
			
			
			String notNullMsg = Optional.ofNullable(res.getString("msg")).orElse("");
			String msgUseable = notNullMsg.length()>499?notNullMsg.substring(0,490):notNullMsg;
			expressOrdersService.updExpressStatus(datasourcekey,res.getString("code"), msgUseable, orderkey);
		} catch (Exception e) {
			res.put("code", "F");
			res.put("msg", e.getMessage());
			log.error("获取快递单号失败");
		}
		

		
		log.info("uuid-{}-获取新快递单号-{}",uuid,res.toJSONString());
		return res.toJSONString();
	}
	
	//将调用到快递单号接口 写入结果表
	private void handelExpressResult(ExpressBO bo,String bodyStr) throws Exception { 
		String carriercode = bo.getExpressConfig().getCarriercode();
		if("ZTOKY".equals(carriercode)) {
			handleZTKYExpressResult(bo,bodyStr);
		}else {
			handleCommonExpressResult(bo); 
		}
	}
	
	//非一次生成子单号的快递接口
	private void handleCommonExpressResult(ExpressBO bo) throws Exception{
		
		String carriercode = bo.getExpressConfig().getCarriercode();
		//修改承运商后备份结果表数据
		bakExpressResult(bo);
		
		bo.getExpressResult().setCarriercode(carriercode);
		expressResultService.addPlExpressResult(bo.getWmwsheid(),bo.getExpressResult());
	}
	

	//一次性生成子单号的快递接口
	private void handleZTKYExpressResult(ExpressBO bo,String bodyStr) throws Exception{
		String carriercode = bo.getExpressConfig().getCarriercode();
		//修改承运商后备份结果表数据
		bakExpressResult(bo);
		
		//中通快运
		//	子单的生成规则就是用（12位主单）+（4位总件数）+（4位（1-总件数））
		//	例如：201800009007，这个主单有5件货，那么第一个子单就是201800009007+0005+0001，第二个子单就是201800009007+0005+0002
		//	以此类推：
		//	201800009007+0005+0003
		//	201800009007+0005+0004
		//	201800009007+0005+0005
		int zdcount = Integer.parseInt(JSON.parseObject(bodyStr).getString("zdcount"));
		
		for(int i=0;i<zdcount;i++) {
			bo.getExpressResult().setCarriercode(carriercode);
			
			String zd = bo.getExpressResult().getWaybillNo()+String.format("%04d", zdcount) + String.format("%04d", i+1);
			bo.getExpressResult().setZtokyzd(zd);
			expressResultService.addPlExpressResult(bo.getWmwsheid(),bo.getExpressResult());
		}
	}
	
	//修改承运商后备份结果表数据
	private void bakExpressResult(ExpressBO bo) throws Exception {
		String carriercode = bo.getExpressConfig().getCarriercode();
		LambdaQueryWrapper<PlExpressResult> query = Wrappers.lambdaQuery();
		query.ne(PlExpressResult::getCarriercode, carriercode);
		query.eq(PlExpressResult::getOrderkey, bo.getExpressTask().getOrderkey());
		List<PlExpressResult> list = expressResultService.selectByWrappers(bo.getWmwsheid(),query);
		if(list !=null && list.size() > 0) {
			for(PlExpressResult each:list) {
				PlExpressResultBak bak = new PlExpressResultBak();
				BeanUtils.copyProperties(bak, each);
				expressResultBakService.addPlExpressResult(bo.getWmwsheid(), bak);
			}
			expressResultService.deleteByWrappers(bo.getWmwsheid(), query);
		}
	}

}
